using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

using Volo.Abp;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Services;

namespace Leo.Core.Domain
{
    public abstract class BaseDomainService<TRepository, TEntity, TKey> : DomainService, IBaseDomainService<TRepository, TEntity, TKey>
        where TKey : struct
        where TEntity : class, IEntity<TKey>
        where TRepository : IBaseAbpRepository<TEntity, TKey>
    {
        protected readonly TRepository _mainRepository;

        protected Action<bool, string> CheckBusinessErrors = (predicate, code) =>
        {
            if (predicate)
            {
                var exception = new BusinessException(code);

                throw exception;
            }
        };

        protected Action<bool, string, Dictionary<string, object>> CheckBusinessErrorsWithData = (predicate, code, datas) =>
        {
            if (predicate)
            {
                var exception = new BusinessException(code);

                if (datas != null)
                {
                    foreach (var data in datas)
                        exception.WithData(data.Key, data.Value);
                }

                throw exception;
            }
        };

        protected BaseDomainService(TRepository mainRepository)
        {
            _mainRepository = mainRepository;
        }

        public async Task<TEntity> InsertAsync(TEntity entity, bool autoSave = false)
        {
            return await _mainRepository.InsertAsync(entity, autoSave);
        }

        /// <summary>
        /// 批量处理
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="autoSave"></param>
        /// <returns></returns>
        public async Task InsertManyAsync(IEnumerable<TEntity> entities, bool autoSave = false)
        {
            await _mainRepository.InsertManyAsync(entities, autoSave);
        }

        public async Task<TEntity> UpdateAsync(TEntity entity, bool autoSave = false)
        {
            return await _mainRepository.UpdateAsync(entity, autoSave);
        }

        public async Task UpdateManyAsync(IEnumerable<TEntity> entities, bool autoSave = false)
        {
            await _mainRepository.UpdateManyAsync(entities, autoSave);
        }

        public async Task DeleteAsync(TEntity entity, bool autoSave = false)
        {
            await _mainRepository.DeleteAsync(entity, autoSave);
        }

        public async Task DeleteManyAsync(IEnumerable<TEntity> entities, bool autoSave = false)
        {
            await _mainRepository.DeleteManyAsync(entities, autoSave);
        }

        public async Task DeleteByIdAsync(TKey id, bool autoSave = false)
        {
            await _mainRepository.DeleteAsync(id, autoSave);
        }

        public async Task<TEntity> GetAsync(TKey id)
        {
            return await _mainRepository.GetAsync(id);
        }

        public async Task<TEntity> FindAsync(TKey id)
        {
            return await _mainRepository.FindAsync(id);
        }

        public async Task<List<TEntity>> GetListByIdAsync(List<TKey> ids)
        {
            return await _mainRepository.GetListAsync(p => ids.Contains(p.Id));
        }

        public async Task<List<TEntity>> GetAllListAsync()
        {
            return await _mainRepository.GetListAsync();
        }


    }
}
